﻿using AutoMapper;
using B.S.ProcessEgine.API.Applocations.Commands.FormNodes;
using B.S.ProcessEgine.Domain.Entities;
using B.S.ProcessEgine.ErrorCode;
using B.S.ProcessEgine.Infractructure.Interfaces;
using MediatR;
using Microsoft.EntityFrameworkCore;
using System.Transactions;

namespace B.S.ProcessEgine.API.Applocations.CommandHandlers.FormNodes
{
    public class AddFormNodeCommandHandler : IRequestHandler<AddFormNodeCommand, ApiResult>
    {
        private readonly IFormNodeRepository formNode;
        private readonly IMapper mapper;
        private readonly IFormInfoRepository formInfo;
        private readonly IFormTypeRepository formType;

        public AddFormNodeCommandHandler(IFormNodeRepository formNode, IMapper mapper, IFormInfoRepository formInfo, IFormTypeRepository formType)
        {
            this.formNode = formNode;
            this.mapper = mapper;
            this.formInfo = formInfo;
            this.formType = formType;
        }
        public async Task<ApiResult> Handle(AddFormNodeCommand request, CancellationToken cancellationToken)
        {
            try
            {
                //先查询表单是否存在
                var Isform = await formInfo.GetAsync(x => x.FormId == request.FormId && !x.IsDel);
                if (Isform == null)
                {
                    return ApiResult.Fail("表单不存在", StateCodeEnum.Fail);
                }

                //查询表单节点名称是否存在
                var Isformnode = await formNode.GetAsync(x => x.NodeName == request.NodeName && !x.IsDel);
                if (Isformnode != null)
                {
                    return ApiResult.Fail("表单节点名称已存在", StateCodeEnum.Fail);
                }

                //开启事务
                using (var tran = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
                {
                    try
                    {
                        //查找当前formid的最大的节点编号（也就是最后一次添加的）  OrderByDescending是根据节点编号进行降序排序，Select是只要节点编号，FirstOrDefaultAsync最后一个
                        string? maxNodesNo = await formNode.GetAll().Where(x => !x.IsDel).OrderByDescending(x => x.NodeNo).Select(x => x.NodeNo).FirstOrDefaultAsync() ?? string.Empty;
                        //定义一个变量，把Command的数据放到变量里
                        Domain.Entities.FormNodes FormNode = mapper.Map<Domain.Entities.FormNodes>(request);

                        //当前编号  "N"+ maxNodesNo.Replace("N","") 是把查找到的最大编号中的N替换为空，若原本是N001，使用Replace替换后则为1，则可获得最大编号的下一位
                        FormNode.NodeNo = "N" + (int.Parse(maxNodesNo.Replace("N", "")) + 1).ToString("D6");

                        //判断数据库是否有formid相同的数据
                        var formCount = await formNode.GetAll().OrderByDescending(x => x.NodeNo).FirstOrDefaultAsync(x => x.FormId == request.FormId && !x.IsDel);
                        var nodes = "";
                        //如果没有，把上级编号设置为空
                        if (formCount == null)
                        {
                            //上级编号
                            FormNode.PrevNodeNo = "";
                            nodes = maxNodesNo;
                        }
                        else
                        {
                            //上级编号
                            FormNode.PrevNodeNo = formCount.NodeNo;
                            nodes = formCount.NodeNo;
                        }

                        //获取当前节点的上级
                        var pervNode = await formNode.GetAsync(x => x.NodeNo == nodes && x.FormId == request.FormId && !x.IsDel);
                        if (pervNode != null)
                        {
                            //则把上级节点的下级编号设置为当前的节点编号
                            pervNode.NextNodeNo = FormNode.NodeNo;
                        }

                        //进行添加操作
                        int res = await formNode.AddAsync(FormNode);

                        //提交事务
                        tran.Complete();
                        //返回APIResult标准返回值
                        return res > 0 ? ApiResult.Success(StateCodeEnum.Ok) : ApiResult.Fail("添加节点失败", StateCodeEnum.Fail);
                    }

                    catch (Exception)
                    {
                        tran.Dispose();
                        return ApiResult.Fail("添加表单异常", StateCodeEnum.Exception);
                    }
                }
            }
            catch (Exception ex)
            {
                throw;
            }
        }
    }
}
